/**
 * TetrisController.m
 * Cocoa Tetris
 *
 * Copyright 2009 Wei Yeh, Evelyn Yung. All rights reserved.
 */

#import "TetrisController.h"

/* Speeds in FPS */
enum Speeds {
	SLOW = 60,
	MEDIUM = 30,
	FAST = 10,
	BASE = SLOW
};

enum States {
	GAME_OVER,
	PAUSED,
	NEW_GAME,
	NEW_TETROMINO,
	MOVING
};

@implementation TetrisController

-(id)init
{
	if (![super init]) return nil;
	
	controller = self;
	
	state = GAME_OVER;
	activeTetromino = nil;
	nextTetromino = nil;
	speed = BASE / 60.0;
	
	musicBackground = [NSSound soundNamed:@"korobeiniki"];
	[musicBackground setLoops:YES];
	soundRotate = [NSSound soundNamed:@"rotate"];
	[soundRotate setVolume:0.1];
	soundClearing = [NSSound soundNamed:@"clear"];
	[soundClearing setVolume:0.10];
	soundTetris = [NSSound soundNamed:@"tetris"];
	[soundTetris setVolume:0.5];
	
	[difficulty setMenu:popupMenu];

	return self;
}

-(int)state
{
	return state;
}

-(IBAction)newGame:(id)sender
{
	switch (state) {
		case GAME_OVER:
			state = NEW_GAME;
			[mainButton setTitle:@"Pause"];
			[self setUpGame];
			break;
		case PAUSED:
			[self resumeGame];
			break;
		case MOVING:
		case NEW_TETROMINO:
			[self pauseGame];
			break;
	}
}

-(void)pauseGame
{
	state = PAUSED;
	[mainButton setTitle:@"Continue"];
	[self stopTick];
	[musicBackground pause];
}

-(void)resumeGame
{
	state = MOVING;
	[mainButton setTitle:@"Pause"];
	[self startTick];
	[musicBackground resume];
}

-(IBAction)openSheet:(NSMenuItem *)item
{
	if (state != GAME_OVER) return;
	[NSApp beginSheet:levelSheet
	   modalForWindow:window
		modalDelegate:self
	   didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
		  contextInfo:nil];
}

-(void)didEndSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{	
    [sheet orderOut:self];
}

-(IBAction)cancel:(id)sender 
{
	[NSApp endSheet:levelSheet];
}

-(IBAction)changeLevel:(id)sender 
{
	[NSApp endSheet:levelSheet];
}

-(void)setUpGame
{
	[self stopTick];
	state = NEW_TETROMINO;
	[board clearAll];
	[miniboard clearAll];
	
	[score setIntValue:0];
	[rowsCleared setIntValue:0];
	
	int newLevel = 0;
	int newFps = BASE;
	switch ([difficulty indexOfSelectedItem]) {
		case 1:
			newLevel = 5;
			newFps = MEDIUM; 
			break;
		case 2:
			newLevel = 10;
			newFps = FAST;
			break;
	}
	speed = newFps / 60.0;
	[level setIntValue:newLevel];
	
	[self startTick];
}

-(void)startTick 
{
	tetrisBoard = board;
	tetrisMiniBoard = miniboard;

	tickTimer = [NSTimer scheduledTimerWithTimeInterval:speed
												 target:self 
											   selector:@selector(tick:) 
											   userInfo:nil 
												repeats:YES];
	
	if ([musicBackground isPlaying]) {
		[musicBackground resume];
	} else {
		[musicBackground play];
	}
}

-(void)stopTick
{
	[tickTimer invalidate];
	tickTimer = nil;
	[musicBackground pause];
}

-(void)tick:(NSTimer *)timer
{
	while (true) {
		switch (state) {
			case NEW_TETROMINO:	/* new state */
				if (nextTetromino == nil) {
					nextTetromino = [Tetromino randomTetromino];
				}
				activeTetromino = nextTetromino;
				[activeTetromino initAtY:(BOARD_LENGTH - 1) x:(BOARD_WIDTH / 2) check:YES];
				if (![activeTetromino setUp]) {
					state = GAME_OVER;
					[mainButton setTitle:@"Start"];
					break;
				}
				nextTetromino = [Tetromino randomTetromino];
				[nextTetromino initAtY:(MINIBOARD_LENGTH / 2) x:((MINIBOARD_WIDTH / 2) + 1) check:NO];
				[nextTetromino setUp];
				state = MOVING;
				break;
			case MOVING:
				if ([activeTetromino canMoveDown]) {
					[activeTetromino moveDown];
				} else {
					[miniboard clearAll];
					int numCleared = [board clear];
					if (numCleared > 0) {
						[self updateStats:numCleared];
						if(numCleared == 4) {
							[soundTetris play];
						} else {
							[soundClearing play];
						}
						[board display];
					}
					state = NEW_TETROMINO;
					continue;
				}
				break;
			}
		break;	/* break while */
	}
	[miniboard display];
	[board display];
}

-(void)move:(unichar)key
{
	switch (key) {
		case NSLeftArrowFunctionKey:
		case 'a':
			[activeTetromino moveLeft];
			[board display];
			break;
		case NSRightArrowFunctionKey:
		case 'd':
			[activeTetromino moveRight];
			[board display];
			break;
		case NSDownArrowFunctionKey:
		case 's':
			[activeTetromino moveDown];
			[board display];
			break;
		case 32:	/* spacebar */
		case NSUpArrowFunctionKey:
		case 'w':
			[activeTetromino rotate];
			[soundRotate play];
			[board display];
			break;
		case 'p':
			if (state == PAUSED) {
				[self resumeGame];
			} else {
				[self pauseGame];
			}
			break;
	}
}

-(void)updateStats:(unsigned int)numCleared
{
	int rowScore = 0;
	switch (numCleared) {
		case 1:
			rowScore = 1;
			break;
		case 2:
			rowScore = 4;
			break;
		case 3:
			rowScore = 7;
			break;
		case 4:
			rowScore = 10;
			break;
	}
	
	[rowsCleared setIntValue:[rowsCleared intValue] + numCleared];
	[score setIntValue:[score intValue] + rowScore];
	
	if ((numCleared > 0) && ([rowsCleared intValue] % 10 == 0)) {
		[self stopTick];
		[level setIntValue:[level intValue] + 1];
		speed -= 0.01;
		[self startTick];
	}
}

@end
